package ast2

import (
	"strconv"
	"strings"
	"sync"

	"gitee.com/u-language/u-language/ucom/data"
	"gitee.com/u-language/u-language/ucom/errcode"
	"gitee.com/u-language/u-language/ucom/lex2"
)

// Package 管理一个包的所有源代码文件的抽象语法树
type Package struct {
	//错误处理上下文
	errctx      *errcode.ErrCtx
	lock        sync.Mutex
	PackageName string
	//符号表
	Sbt *Sbt
	//保存抽象语法树
	Trees data.Slice[*Tree]
	//是否有init函数
	IsInitFunc bool
	//C语言头文件用到的节点
	CHeaderFile data.Slice[CDecl]
	//变量初始化
	VarInitTable VarInitTable
	//自己及依赖导入的包
	ImportPackage map[string]*Package
	//是所有的导入路径
	ImporPath *Sbt
	//并发
	Thread bool
}

// NewPackage 创建管理一个包的所有源代码文件的抽象语法树的 [Package]
//   - dir是包的路径
//   - thread是控制是否并发
//   - errctx是错误处理上下文
//   - sbt是符号表
func NewPackage(dir string, thread bool, errctx *errcode.ErrCtx, sbt *Sbt, ImportPackage map[string]*Package) *Package {
	ret := &Package{
		Thread:        thread,
		errctx:        errctx,
		Trees:         data.Slice[*Tree]{Thread: thread},
		Sbt:           sbt,
		CHeaderFile:   data.Slice[CDecl]{Thread: thread},
		ImportPackage: ImportPackage,
		ImporPath:     NewSbt(thread),
	}
	ret.VarInitTable.Init(thread)
	return ret
}

// AddFile 将一个源代码文件的词法分析结果转换为抽象语法树保存
//   - ft 是源代码文件的词法分析结果
func (p *Package) AddFile(ft lex2.FileToken) {
	tree := Tree{}
	tree.newTree(p.Sbt, ft, p.errctx, &p.IsInitFunc, &p.VarInitTable, &p.CHeaderFile, &p.ImportPackage, p.ImporPath)
	tree.Parser()
	p.lock.Lock()
	p.PackageName = tree.PackageName
	p.lock.Unlock()
	p.Trees.Add(&tree)
}

func (p *Package) String() string {
	var buf strings.Builder
	buf.WriteString("package: ")
	buf.WriteString(p.PackageName)
	buf.WriteString("\n")
	for _, v := range p.Trees.Data {
		buf.WriteString(v.Filename)
		buf.WriteString("\n\n")
		for i, n := range v.Nodes {
			buf.WriteString(strconv.Itoa(i))
			buf.WriteString(n.String())
			buf.WriteString("\n")
		}
	}
	buf.WriteString(p.Sbt.String())
	buf.WriteString("\n")
	return buf.String()
}
